import hashlib
import hmac
import requests.auth
import time
import urllib.parse
import sys
import json
import datetime

from coin2.api_client.common import (SyncQueryer)
from coin.exchange.base.kr_rest.auth_base import AuthKey


class GateioAuth(requests.auth.AuthBase):
  def __init__(self, key):
    self._key = AuthKey.from_file(key)

  def _gen_signature(self, method, url, query_string=None, payload_string=None):
    t = time.time()
    m = hashlib.sha512()
    m.update((payload_string or "").encode('utf-8'))
    hashed_payload = m.hexdigest()
    s = '%s\n%s\n%s\n%s\n%s' % (
        method, url, query_string or "", hashed_payload, t)
    sign = hmac.new(self._key.secret_key.encode('utf-8'),
                    s.encode('utf-8'), hashlib.sha512).hexdigest()
    return {'KEY': self._key.api_key, 'Timestamp': str(t), 'SIGN': sign}

  def __call__(self, req: requests.PreparedRequest):
    request = urllib.parse.urlparse(req.url)
    signature = self._gen_signature(
        req.method, request.path, request.query, req.body)
    req.headers.update({'Accept': 'application/json',
                       'Content-Type': 'application/json'})
    req.headers.update(signature)
    return req


class GateioPrivateClient():
  def __init__(self, key, mea):
    self._key = key
    self._auth = GateioAuth(key)
    if mea == "Spot.Gateio.v4":
      self._url = 'https://api.gateio.ws'
    else:
      assert (0)

    self._query = SyncQueryer(api_host=self._url, auth=self._auth)

  def get_fill_history(
    self,
    currency_pair: str=None,
    limit: int=None,
    page: int=None,
    order_id: str=None,
    account: str=None,
    timestamp_from: int=None,
    timestamp_to: int=None,
  ):
    method = "GET"
    prefix = "/api/v4"
    path = '/spot/my_trades'
    params = {
      "currency_pair": currency_pair,
      "limit": limit,
      "page": page,
      "order_id": order_id,
      "account": account,
      "from": timestamp_from,
      "to": timestamp_to,
    }
    response = self._query.query(
        method=method, path=prefix + path, params=params)
    return response

  def get_open_order(self):
    method = "GET"
    prefix = "/api/v4"
    path = '/spot/open_orders'
    params = None
    response = self._query.query(
        method=method, path=prefix + path, params=params)
    return response

  def cancel_order(self, order_id, currency_pair: str):
    path = '/spot/orders/' + str(order_id)
    method = "DELETE"
    prefix = "/api/v4"
    params = {"currency_pair": currency_pair}
    response = self._query.query(
        method=method, path=prefix + path, params=params)
    return response

  def wallet_withdrawals(self):
    path = "/wallet/withdrawals"
    method = "GET"
    prefix = "/api/v4"
    params = {"from": 1663846108895, "limit": 100, "to": 1664450908895}
    response = self._query.query(
        method=method, path=prefix + path, params=params)
    return response

  def wallet_deposits(self):
    path = "/wallet/deposits"
    method = "GET"
    prefix = "/api/v4"
    response = self._query.query(
        method=method, path=prefix + path)
    return response

  def wallet_sub_account_transfers(self, strat: datetime.datetime, end: datetime.datetime):
    path = "/wallet/sub_account_transfers"
    method = "GET"
    prefix = "/api/v4"

    params = {"limit": 500, "from": strat.timestamp(), "to": end.timestamp()}
    response = self._query.query(
        method=method, path=prefix + path, params=params)
    return response

  def deposit_address(self, currency):
    path = "/wallet/deposit_address"
    method = "GET"
    prefix = "/api/v4"
    param = {"currency": currency}  # "USDT"
    response = self._query.query(
        method=method, path=prefix + path, params=param)
    return response

  def cancel_order_all(self):
    while True:
      req = gate.get_open_order()
      req = req.json()
      if len(req) == 0:
        return
      for item in req:
        currency_pair = item["currency_pair"]
        for order in item["orders"]:
          id = order["text"]
          print("cancel info ", id, "   ", currency_pair)
          gate.cancel_order(id, currency_pair)

  def get_order_fill(self, symbol: str, begin_time, end_time):
    path = "/spot/my_trades"
    method = "GET"
    prefix = "/api/v4"
    param = {"currency_pair": symbol, "limit": 1000, "from":begin_time , "to": end_time}
    response = self._query.query(
        method=method, path=prefix + path, params=param)
    return response

  def get_account_balance(self):
    path = "/wallet/total_balance"
    method = "GET"
    prefix = "/api/v4"
    response = self._query.query(method=method, path=prefix + path)
    return response

def to_seconds(time:datetime.datetime):
  return int(time.timestamp())

if __name__ == "__main__":
  key = sys.argv[1]
  config = {"key_path": key, "mea": "Spot.Gateio.v4"}
  gate = GateioPrivateClient(key, "Spot.Gateio.v4")

  info = gate.get_account_balance()
  info = info.json()
  info = json.dumps(info, indent=2)

  print(info)

# https://www.gate.io/docs/developers/apiv4/en/#gate-api-v4-v4-35-0